feat: typed assess errors + X-Quota headers + signer_match types#26
Merged
vvillait88 merged 10 commits intomainfrom May 2, 2026
Merged
feat: typed assess errors + X-Quota headers + signer_match types#26vvillait88 merged 10 commits intomainfrom
vvillait88 merged 10 commits intomainfrom
Conversation
…ring The API itself gates the endpoint by tier; the SDK doesn't need to remind callers about tier structure in a docstring. Consistent with the platform-wide pass to keep tier/pricing language out of public-package source. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…rMatch
- New error subclasses (all subclass AgentScoreError so existing catches still work):
PaymentRequiredError (402), TokenExpiredError (401 token_expired with parsed body
fields exposed: verifyUrl/sessionId/pollSecret/pollUrl/nextSteps/agentMemory),
InvalidCredentialError (401 invalid_credential), QuotaExceededError (429 quota_exceeded),
RateLimitedError (429 rate_limited), TimeoutError (AbortError / request timeout)
- AssessResponse gains optional quota field { limit, used, reset } captured from
X-Quota-Limit / X-Quota-Used / X-Quota-Reset response headers; agents can monitor
approach-to-cap proactively (warn at 80%, alert at 95%) before hitting 429
- New telemetrySignerMatch(payload) method — fire-and-forget POST to
/v1/telemetry/signer-match (commerce gate currently does this raw; will switch)
- Internal: request<T>() splits into request<T>() + requestWithHeaders<T>(); shared
buildErrorFromResponse helper does status+code routing once
Backward-compatible: all new error classes inherit AgentScoreError; existing
catch (err: AgentScoreError) blocks unaffected. New quota field is optional.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…emetrySignerMatch - README: new "Typed error classes" subsection with class table + recovery example; "Quota observability" section showing how to read AssessResponse.quota; "Telemetry" section noting the new fire-and-forget method. - CLAUDE.md: telemetrySignerMatch added to Methods; new "Errors + observability" section enumerating all 6 typed error subclasses + the quota field. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Second-pass review caught: Number('') is 0 (truthy, finite) while Python int('')
raises ValueError. Same for decimals — Number('1.5') is 1.5; int('1.5') raises.
A misconfigured proxy or test sending malformed X-Quota-* headers would surface
0 / 1.5 in node but null in python.
Replace `Number(raw)` + `isFinite` with regex `^-?\\d+$` test, matching int()'s
strict integer-only behavior. Empty strings, decimals, scientific notation, and
non-numeric strings now all return null in both SDKs.
Test added for empty + decimal headers (returns null) — parity with python-sdk's
existing test_extract_quota_falls_back_to_none_for_malformed_numeric_headers.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Captures TEC-274 minor: new public exports (PaymentRequiredError, TokenExpiredError, InvalidCredentialError, QuotaExceededError, RateLimitedError, TimeoutError) + AssessResponse.quota field + telemetrySignerMatch method. Skips intermediate 2.1.2 (docstring-only commit on this branch was unreleased). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pre-existing line, not introduced by TEC-274 work, but caught while sweeping
node-sdk tests for tier-language under feedback_no_internal_disclosure_in_public.
Tests are part of the public-package surface; "(free tier)" leaks our tier
structure. Replaced with the actual error semantics ("endpoint not enabled").
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Self-review (parallel agents) found three test gaps + one misleading comment: - parseQuotaNumber comment claimed Python int() doesn't trim whitespace / reject decimals — both wrong; Python int() does both. Reworded to describe Number() + parseInt() pitfalls (the actual reason for the regex), not Python diff. Added tests: - 429 → 200 retry path captures quota headers from the RETRY response (not the discarded original 429). Regression guard for requestWithHeaders retry logic. - Generic 4xx fallthrough — 400 invalid_request and 403 account_cancelled both fall through to generic AgentScoreError (not any typed subclass). Verifies the discriminator only fires for the documented status+code pairs. - TokenExpiredError with empty body — all parsed-body fields stay undefined, instance is still TokenExpiredError (not generic AgentScoreError fallthrough). - TokenExpiredError with wrong-typed body fields — the typeof string check silently ignores number/array values; raw values still flow through `details`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…lemetry/signer-match Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…h assess Add ResolveSigner request type and SignerMatch response type matching the API's new server-side wallet-signer-match. assess() and the AssessOptions shape gain an optional resolveSigner field; AssessResponse gains optional signer_match. Drop vestigial on_the_fly + updated_at fields from AssessResponse — they were never read by any caller. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
AssessErrortaxonomy on assess responses (paymentRequired, quotaExceeded, identityRequired, signerMismatch, etc.) so consumers can branch on denial codes without parsing stringsX-Quota-Limit/X-Quota-Used/X-Quota-Resetresponse headers onAssessResponsefor merchant-side observabilityResolveSignerrequest type +SignerMatchresponse type so SDK consumers can opt into server-side signer matching on/v1/assess(TEC-263 SDK side)telemetrySignerMatch()method for posting gate-side outcomes to the telemetry endpointparseQuotaNumberto strict-integer parity with python-sdkCloses TEC-274.
Test plan
bun run test)bun run buildproduces clean tsup output🤖 Generated with Claude Code